package cc.yaomm.common.biz.business;

import cc.yaomm.common.basic.annotation.Permission;
import cc.yaomm.common.basic.enums.AuthLevelEnum;
import cc.yaomm.common.biz.enums.SystemEnum;
import cc.yaomm.common.biz.enums.ServeTypeEnum;
import cc.yaomm.common.biz.lang.bo.ResourceBO;
import com.google.common.base.Joiner;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.EmbeddedValueResolver;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;

import java.util.*;

/**
 * Created by XQL on 2021/6/9.
 */
@Slf4j
public class BaseInitResource {

    @Autowired
    private EmbeddedValueResolver embeddedValueResolver;

    private String[] emptyArray = new String[]{""};

    protected List<ResourceBO> getResources(HandlerMethod handlerMethod, ServeTypeEnum serveTypeEnum) {
        //查找类上的注解
        RequestMapping clazzRequestAnn = handlerMethod.getBeanType().getAnnotation(RequestMapping.class);
        //查找方法上的注解
        RequestMapping methodRequestAnn = handlerMethod.getMethodAnnotation(RequestMapping.class);
        //获取接口描述注解
        ApiOperation apiOperation = handlerMethod.getMethodAnnotation(ApiOperation.class);
        //获取方法上的权限注解
        Permission permissionAnn = handlerMethod.getMethodAnnotation(Permission.class);
        //如果方法上的权限注解为空时，获取类上注解
        permissionAnn = permissionAnn == null ? handlerMethod.getBeanType().getAnnotation(Permission.class) : permissionAnn;

        //判断是否登录
        AuthLevelEnum authLevelEnum = permissionAnn == null ? AuthLevelEnum.AUTH : permissionAnn.value();

        String[] clazzMappings = clazzRequestAnn == null || ArrayUtils.isEmpty(clazzRequestAnn.value()) ? emptyArray : clazzRequestAnn.value();
        String[] methodMappings = methodRequestAnn == null || ArrayUtils.isEmpty(methodRequestAnn.path()) ? emptyArray : methodRequestAnn.path();
        RequestMethod[] methods = Objects.nonNull(methodRequestAnn) ? methodRequestAnn.method() : new RequestMethod[0];

        Set<String> mappings = new HashSet<>(1);
        for (String clazzMapping : clazzMappings) {
            for (String methodMapping : methodMappings) {
                String path = Joiner.on("/").join(clazzMapping, methodMapping).replaceAll("([//])\\1{1,}", "$1");
                path = embeddedValueResolver.resolveStringValue(path);
                mappings.add("/".concat(path));
            }
        }

        List<ResourceBO> resources = new ArrayList<>();
        for (RequestMethod requestMethod : methods) {
            for (String mapping : mappings) {
                //匹配获取应用
                SystemEnum appsEnum = Arrays.stream(SystemEnum.values())
                        .filter(apps -> mapping.toLowerCase().startsWith(apps.getValue().toLowerCase(), 1))
                        .findFirst()
                        .orElse(null);
                if (Objects.isNull(appsEnum)) {
                    log.warn("初始化接口资源时，没有找到{}所属应用类型", mapping);
                    continue;
                }

                //接口描述
                resources.add(ResourceBO.builder()
                        .name(Objects.isNull(apiOperation) || StringUtils.isBlank(apiOperation.value()) ? "未知描述" : apiOperation.value())
                        .method(requestMethod.name())
                        .url(mapping)
                        .code(DigestUtils.md5DigestAsHex((requestMethod.name() + ":" + mapping).getBytes()))
                        .ownerServe(serveTypeEnum)
                        .authLevel(authLevelEnum)
                        .ownerApp(appsEnum)
                        .build());
            }
        }
        return resources;
    }
}
